package com.gopay.common.util.xml.xmlutils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;

import com.gopay.common.util.xml.xmlutils.message.Message;
import com.gopay.common.util.xml.xmlutils.message.Validator;
import com.gopay.common.util.xml.xmlutils.message.xml.vo.BFNode;
import com.gopay.common.util.xml.xmlutils.message.xml.vo.Bean;
import com.gopay.common.util.xml.xmlutils.message.xml.vo.Field;

/**
 * 
 * @author liujy
 *
 */
public class MessagesBuilder {
    private static final String SELECT_ELEMENT_MESSAGE = "/messages/message";
    private static final String SELECT_VALIDATOR_MESSAGE = "message";
    private static final String SELECT_VALIDATOR_ERROR_CODE = "errorcode";

    private static MessagesBuilder messagesBuilder = new MessagesBuilder();

    private MessagesBuilder() {
    }

    public static MessagesBuilder getInstance() {
        return messagesBuilder;
    }

    public Map<String, Message> builder(Document document) throws Exception {
        return builderMessages(document);
    }
    
    /**
     * 拼装FORM对象
     * 
     * @return
     */
    @SuppressWarnings("unchecked")
    private Map<String, Message> builderMessages(Document document) throws Exception {
        if (document == null) {
            return null;
        }
        List<Element> messageEs = document.selectNodes(SELECT_ELEMENT_MESSAGE);
        if (messageEs == null || messageEs.size() == 0) {
            return null;
        }
        
        Map<String, Message> messageMap = new HashMap<String, Message>();
        
        for (int i = 0, size = messageEs.size(); i < size; i++) {
            Message m = builderMessage(messageEs.get(i));
            messageMap.put(m.getMsgType(), m);
        }
        
        return messageMap;
    }
    
    /**
     * 
     * @param messageE
     * @return
     */
    @SuppressWarnings("unchecked")
	private Message builderMessage(Element messageE){
    	
    	Message message = new Message();
    	List<Bean> beans = new ArrayList<Bean>();
    	
    	List<Element> beanEs = messageE.selectNodes("beans/bean");
    	for(int i = 0, size = beanEs.size(); i < size; i++){
    		Bean bean = builderBean(beanEs.get(i));
    		beans.add(bean);
    	}
    	message.setMsgType(messageE.attributeValue("msgType"));
    	message.setBeans(beans);
    	return message;
    }
    
    /**
     * 
     * @param beanE
     * @return
     */
    @SuppressWarnings("unchecked")
	private Bean builderBean(Element beanE) {
		
    	Bean bean = new Bean();
		
		String beanType = beanE.attributeValue("beanType");
		String type = beanE.attributeValue("type");
		String path = beanE.attributeValue("path");
		String name = beanE.attributeValue("name");
		bean.setBeanType(beanType);
		bean.setType(type);
		bean.setPath(path);
		bean.setName(name);
		
		List<Element> fieldEs = beanE.elements("field");
		if(fieldEs == null || fieldEs.size() < 1){
			return bean;
		}
		
		List<BFNode> nodes = new ArrayList<BFNode>();
		for (int i = 0, size = fieldEs.size(); i < size; i++) {
			Field field = builderField(fieldEs.get(i));
			nodes.add(field);
		}
		bean.setNodes(nodes);
		
		List<Element> beanEs = beanE.elements("bean");
		if(beanEs == null || beanEs.size() < 1){
			return bean;
		}
		
		List<BFNode> beans = new ArrayList<BFNode>();
		for (int i = 0, size = beanEs.size(); i < size; i++) {
			Bean bean0 = builderBean(beanEs.get(i));
			nodes.add(bean0);
		}
		
		bean.getNodes().addAll(beans);
		
		
		return bean;
	}

    /**
     * 
     * @param element
     * @return
     */
	@SuppressWarnings("unchecked")
	private Field builderField(Element fieldE) {
		Field field = new Field();
		List<Validator> validators = new ArrayList<Validator>();
		String name = fieldE.attributeValue("name");
		String type = fieldE.attributeValue("type");
		String path = fieldE.attributeValue("path");
		String style = fieldE.attributeValue("style");
		String defaultValue = fieldE.attributeValue("default");
		String isElement = fieldE.attributeValue("isElement");
		field.setName(name);
		field.setType(type);
		field.setPath(path);
		field.setStyle(style);
		field.setDefaultValue(defaultValue);
		if(StringUtils.equals("false", isElement)){
			field.setElement(false);
		}else{
			field.setElement(true);
		}
		
		List<Element> validatorEs = fieldE.elements("validator");
		if(validatorEs == null || validatorEs.size() < 1){
			return field;
		}
		for(int i = 0, size = validatorEs.size(); i < size; i++){
			Validator v = builderValidator(validatorEs.get(i));
			validators.add(v);
		}
		field.setValidators(validators);
		return field;
	}

	/**
	 * 
	 * @param element
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private Validator builderValidator(Element element) {
        if (element == null) {
            return null;
        }
        Validator validator = new Validator();
        String requried = element.attributeValue("required");
        String minLength = element.attributeValue("minLength");
        String maxLength = element.attributeValue("maxLength");
        String pattern = element.attributeValue("pattern");
        String minValue = element.attributeValue("minValue");
        String maxValue = element.attributeValue("maxValue");
        String compareTo = element.attributeValue("compareTo");
        String value = element.attributeValue("value");
        String type = element.attributeValue("type");
        String combinationField = element.attributeValue("combinationField");
        String message = null;
        List<Element> messageEle = element.selectNodes(SELECT_VALIDATOR_MESSAGE);
        String errorCode = null;
        List<Element> errorCodeEle = element.selectNodes(SELECT_VALIDATOR_ERROR_CODE);
        if (messageEle != null) {
            for (Iterator<Element> it = messageEle.iterator(); it.hasNext();) {
                Element e = (Element) it.next();
                message = e.getText();
                break;
            }
        }
        if (errorCodeEle != null) {
            for (Iterator<Element> it = errorCodeEle.iterator(); it.hasNext();) {
                Element e = (Element) it.next();
                errorCode = e.getText();
                break;
            }
        }
        if (StringUtils.isNotBlank(requried) && StringUtils.equalsIgnoreCase("true", requried)) {
            validator.setRequired(true);
        }
        if (StringUtils.isNotBlank(minLength)) {
            validator.setMinLength(minLength);
        }
        if (StringUtils.isNotBlank(maxLength)) {
            validator.setMaxLength(maxLength);
        }
        if (StringUtils.isNotBlank(minValue)) {
            validator.setMinValue(minValue);
        }
        if (StringUtils.isNotBlank(maxValue)) {
            validator.setMaxValue(maxValue);
        }
        validator.setPattern(pattern);
        validator.setCompareTo(compareTo);
        validator.setValue(value);
        validator.setType(type);
        validator.setCombinationField(combinationField);
        validator.setMessage(message);
        validator.setErrorCode(errorCode);
        return validator;
    
	}
}